package org.ma1.cripto.aes.ppal;

import org.ma1.cripto.aes.comun.Bloque;
import org.ma1.cripto.aes.comun.Clave;
import org.ma1.cripto.aes.operacion.IOperacion;
import org.ma1.cripto.aes.operacion.OperacionBuilder;

public class DescifrarState implements IState {
	private IOperacion[] operaciones = null;
	private int indiceClaveDeRonda = 0;
	private Clave[] clavesDeRonda = null;

	public DescifrarState() {
	}

	public IOperacion getOperacion(int i) {
		if (i>=operaciones.length)
			return null;
		return operaciones[i];
	}

	public String getNombreOperacion(int i) {
		if (i>=operaciones.length || i<0) {
			return null;
		}
		return operaciones[i].getNombre();
	}

	public void setRondas(int Nr, Clave[] clavesDeRonda) {
		OperacionBuilder constructor = OperacionBuilder.getCurrentInstance();
		operaciones = new IOperacion[4*Nr];
		operaciones[0] = constructor.createOperacion(OperacionBuilder.AddRoundKey);
		for (int k=1; k<4*(Nr-1);) {
			operaciones[k++]=constructor.createOperacion(OperacionBuilder.InvShiftRow);
			operaciones[k++]=constructor.createOperacion(OperacionBuilder.InvByteSub);
			operaciones[k++]=constructor.createOperacion(OperacionBuilder.AddRoundKey);
			operaciones[k++]=constructor.createOperacion(OperacionBuilder.InvMixColumns);
		}
		operaciones[1+4*(Nr-1)+ 0 ] = constructor.createOperacion(OperacionBuilder.InvShiftRow);
		operaciones[1+4*(Nr-1)+ 1 ] = constructor.createOperacion(OperacionBuilder.InvByteSub);
		operaciones[1+4*(Nr-1)+ 2 ] = constructor.createOperacion(OperacionBuilder.AddRoundKey);
		this.clavesDeRonda = clavesDeRonda;
		this.indiceClaveDeRonda = this.clavesDeRonda.length-1;
	}

	public Bloque doStep(int i, Bloque bloque) {
		Clave clave = null;
		IOperacion operacion = getOperacion(i);
		if (operacion==null) return null;
		if (getNombreOperacion(i).equals(OperacionBuilder.AddRoundKey)) {
			clave = clavesDeRonda[indiceClaveDeRonda--];
		}
		Bloque ret = operacion.operacion(bloque, clave);
		return ret;
	}

	public void nuevaRonda() {
		indiceClaveDeRonda = this.clavesDeRonda.length-1;
	}
}
